import { validate } from "schema-utils"
import rawLoadLanguages from "prismjs/components/index.js"
import { useMarkdownResolver, MarkdownLoaderContent, MarkdownResolver } from "../utils/index.js"

rawLoadLanguages.silent = true

// 语言加载
const loadLanguages = (languages: string[] | "all"): void => {
  if (languages === "all") rawLoadLanguages()
  else if (languages.length) rawLoadLanguages(languages)
}

// 除默认 markup, css, clike and javascript 外
// 额外预加载以下语言
loadLanguages(["md", "html", "jsx", "ts", "tsx", "bash"])

/* markdownResolver：使用同一个函数markdown对象，避免重复创建 */
let markdownResolver: MarkdownResolver | null = null
export default function MarkdownLoader(source: string): string {
  const loaderContext: MarkdownLoaderContent = this
  const options = loaderContext.getOptions()

  validate(
    {
      type: "object",
      properties: {
        languages: {
          anyOf: [{ type: "array" }, { type: "string" }],
          description: `prismjs 加载的代码块语言类型："all" | [langs]。`,
          link: "https://prismjs.com/#supported-languages"
        },
        languageMap: {
          type: "object",
          description: `prismjs无法解析语言的映射：{ 读取的语言: 目标语言 }`
        },
        html: {
          type: "boolean",
          description: `markdown-it 配置：是否在源码中启用 HTML 标签`
        },
        xhtmlOut: {
          type: "boolean",
          description: `markdown-it 配置：是否使用 "/" 来闭合单标签`
        },
        breaks: {
          type: "boolean",
          description: `markdown-it 配置：转换段落里的 '\n' 到 <br>`
        },
        langPrefix: {
          type: "string",
          description: `markdown-it 配置：<pre /> 代码块的 CSS 类名前缀`
        },
        linkify: {
          type: "boolean",
          description: `markdown-it 配置：将类似 URL 的文本自动转换为链接`
        },
        typographer: {
          type: "boolean",
          description: `markdown-it 配置：启用一些语言中立的替换 + 引号美化`
        },
        quotes: {
          type: "string",
          description: `markdown-it 配置：双 + 单引号替换对，当 typographer 启用时`
        },
        handler: {
          instanceof: "Function",
          description: `使用 markdown 实例作为入参，提供更好的自定义`
        },
        codeHandler: {
          instanceof: "Function",
          description: `在抛给 markdown-it 之前，对高亮解析后的代码块 html 进行二次处理`
        },
        useAnchor: {
          type: "boolean",
          description: `是否使用 markdown-it-anchor 插件`
        },
        anchorOptions: {
          type: "object",
          description: `markdown-it-anchor 的配置`
        },
        useTOC: {
          type: "boolean",
          description: `是否使用 markdown-it-toc-done-right 插件`
        },
        TOCOptions: {
          type: "object",
          description: `markdown-it-toc-done-right 的配置`
        },
        useContainer: {
          type: "boolean",
          description: `是否使用 markdown-it-container 插件`
        },
        containerOptions: {
          type: "object",
          description: `markdown-it-container 配置`
        }
      }
    },
    options,
    {
      name: "MarkdownLoader",
      baseDataPath: "options"
    }
  )

  if (!markdownResolver) {
    const { languages = [], ...resolverOptions } = options

    markdownResolver = useMarkdownResolver(resolverOptions, loaderContext)

    // 加载语言
    loadLanguages(languages)
  }

  // 解析文本
  const { html, TOCCode } = markdownResolver.resolver(source)

  // 1. 使用 JSON.stringify 序列化特殊字符
  // 2. 使用 export default 输出字符串
  return `export default ${JSON.stringify({ source, html, TOCCode })}`
}
